package com.ctl.juc;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;


public class CompletableFutureTest3 {
    static Logger logger = LoggerFactory.getLogger(CompletableFutureTest3.class);
    static final Integer sleepTime = 1000;

    public static Integer calc(Integer para) {
        try {
            //模拟一个长时间的执行
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            logger.error("", e);
        }
        return para * para;
    }

    public static void main(String[] args) throws Exception {
        final CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> calc(50))
                .thenApply((i) -> {
                    logger.info("Integer {} to String ", i);
                    return Integer.toString(i);
                }).thenApply((str) -> {
                    logger.info("原始str={}", str);
                    return "[" + str + "]";
                }).thenAccept((string) -> {
                    logger.info("最终结果={}", string);
                });
        future.get();
        acceptEither();
//        Thread.sleep(sleepTime);//保证f1和f2都能执行完
        futureF.get();//保证f1和f2其中一个执行完
    }

    static final CompletableFuture<String> futureF = new CompletableFuture<>();

    private static void acceptEither() throws Exception {
        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
            logger.info("f1 start");
            int t = new Random().nextInt(sleepTime);
            try {
                TimeUnit.MILLISECONDS.sleep(t);
            } catch (InterruptedException e) {
                logger.error("", e);
            }
            logger.info("f1 return={}", t);
            return "f1-" + t;
        });

        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
            logger.info("f2 start");
            int t = new Random().nextInt(sleepTime);
            try {
                TimeUnit.MILLISECONDS.sleep(t);
            } catch (InterruptedException e) {
                logger.error("", e);
            }
            logger.info("f2 return={}", t);
            return "f2-" + t;
        });
//            f1.acceptEitherAsync(f2, t -> {
            f1.acceptEither(f2, t -> {
                logger.info("f1 acceptEither f2,{}", t);
                futureF.complete("over");
            });


    }

}